package com.yejiarong.weather.agent.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.yejiarong.weather.agent.bean.entity.WeatherRegionCode;
import com.yejiarong.weather.agent.mapper.IWeatherRegionCodeMapper;
import com.yejiarong.weather.agent.service.IWeatherRegionCodeService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author YeJR
 */
@Slf4j
@Service
public class WeatherRegionCodeServiceImp implements IWeatherRegionCodeService {

    private final IWeatherRegionCodeMapper weatherRegionCodeMapper;

    public WeatherRegionCodeServiceImp(IWeatherRegionCodeMapper weatherRegionCodeMapper) {
        this.weatherRegionCodeMapper = weatherRegionCodeMapper;
    }

    /**
     * 保存区域编码
     *
     * @param regionCodeMap 省 -> 市 -> 区 -> 编码
     */
    @Override
    public void saveWeatherRegionCode(Map<String, Map<String, Map<String, String>>> regionCodeMap) {
        if (MapUtils.isEmpty(regionCodeMap)) {
            return;
        }
        for (Map.Entry<String, Map<String, Map<String, String>>> entry : regionCodeMap.entrySet()) {
            String province = entry.getKey();
            Map<String, Map<String, String>> provinceMap = entry.getValue();
            for (Map.Entry<String, Map<String, String>> entry1 : provinceMap.entrySet()) {
                String city = entry1.getKey();
                Map<String, String> countyCodeMap = entry1.getValue();
                if (MapUtils.isEmpty(countyCodeMap)) {
                    return;
                }
                // 查询原有数据
                LambdaQueryWrapper<WeatherRegionCode> queryWrapper = new LambdaQueryWrapper<WeatherRegionCode>().eq(WeatherRegionCode::getProvince, province).eq(WeatherRegionCode::getCity, city);
                List<WeatherRegionCode> weatherRegionCodes = weatherRegionCodeMapper.selectList(queryWrapper);

                List<WeatherRegionCode> newWeatherRegionCodes = new ArrayList<>();
                List<WeatherRegionCode> oldWeatherRegionCodes = new ArrayList<>();

                Map<String, WeatherRegionCode> countyMap = weatherRegionCodes.stream().collect(Collectors.toMap(WeatherRegionCode::getCounty, o -> o, (a, b) -> b));
                for (Map.Entry<String, String> entry2 : countyCodeMap.entrySet()) {
                    WeatherRegionCode weatherRegionCode = countyMap.remove(entry2.getKey());
                    if (weatherRegionCode == null) {
                        weatherRegionCode = new WeatherRegionCode();
                        newWeatherRegionCodes.add(weatherRegionCode);
                        weatherRegionCode.setCreateTime(LocalDateTime.now());
                    } else {
                        oldWeatherRegionCodes.add(weatherRegionCode);
                        weatherRegionCode.setUpdateTime(LocalDateTime.now());
                    }
                    weatherRegionCode.setProvince(province);
                    weatherRegionCode.setCity(city);
                    weatherRegionCode.setCounty(entry2.getKey());
                    weatherRegionCode.setCode(entry2.getValue());
                }

                List<WeatherRegionCode> disappearedWeatherRegionCodes = new ArrayList<>(countyMap.values());

                // 保存数据
                if (CollectionUtils.isNotEmpty(newWeatherRegionCodes)) {
                    weatherRegionCodeMapper.batchInsert(newWeatherRegionCodes);
                }
                if (CollectionUtils.isNotEmpty(oldWeatherRegionCodes)) {
                    oldWeatherRegionCodes.forEach(weatherRegionCode -> {
                        LambdaUpdateWrapper<WeatherRegionCode> updateWrapper = new LambdaUpdateWrapper<WeatherRegionCode>().set(WeatherRegionCode::getCode, weatherRegionCode.getCode()).set(WeatherRegionCode::getUpdateTime, weatherRegionCode.getUpdateTime()).eq(WeatherRegionCode::getId, weatherRegionCode.getId());
                        weatherRegionCodeMapper.update(updateWrapper);
                    });
                }
                if (CollectionUtils.isNotEmpty(disappearedWeatherRegionCodes)) {
                    List<Long> ids = disappearedWeatherRegionCodes.stream().map(WeatherRegionCode::getId).collect(Collectors.toList());
                    weatherRegionCodeMapper.deleteByIds(ids);
                }
            }
        }

    }
}
